import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class PbxTest {
	public static void main(String[] args) {

		// 路由列表
		String s = "{\"default\":{\"type\":\"ivr\",\"target\":\"1\"},\"64431168\":{\"type\":\"ivr\",\"target\":\"1\"},\"64432168\":{\"type\":\"rxfax\",\"target\":\"\"},\"8880\":{\"type\":\"to-ivr\",\"target\":\"1\",\"zone0\":\"8:00~23:00#0123456\",\"zone0_type\":\"to-queue\",\"zone0_target\":\"1\",\"zone1\":\"23:00~8:00#12345\",\"zone1_type\":\"to-meet\",\"zone1_target\":\"1\"}}";
		Gson gson = new Gson();
		Map<String, Route> m = gson.fromJson(s, C.mapRoute);
		for (String key : m.keySet()) {
			Route r = m.get(key);
			System.out.println(gson.toJson(r));
		}

		// Ivr列表
		s = "{\"1\":{\"url\":\"http://127.0.0.1/vxml/so/switch.php\"},\"2\":{\"url\":\"http://127.0.0.1/vxml/so/message.php\",\"0_9\":\"trans!to-rxfax!1\",\"0\":\"switch!test/101!10!3!4!8\",\"0_1_02\":\"trans!to-in!8002\",\"0_1_default\":\"exit\",\"0_1_01\":\"trans!to-in!8001\",\"0_1\":\"field!test/102!10!3!2\",\"0_0\":\"trans!to-in!8000\",\"0_default\":\"exit\",\"0_3\":\"play!test/103\",\"0_3_default\":\"exit\"}}";
		Map<String, Map<String, String>> ilist = gson.fromJson(s, C.mapIvr);
		for (String key : ilist.keySet()){
			System.out.println(String.format("[----IVR  %s----]", key));
			Map<String, String> ivr = ilist.get(key);
			for (String label : ivr.keySet()){
				String act = ivr.get(label);
				System.out.println(String.format("%s=%s", label, act));
			}
		}
		

		// IVR
		String node = IvrOperation.mainMenu;
		Map<String, String> ivr = IvrOperation.genIvr();
		// 交换主菜单, 如 请直拨分机号,查号请拨0,部门查询请拨1,公司简介请按3,传真请拨9
		IvrAction action = new SwitchAction("test/101", "4", "8");
		IvrOperation.addMain(ivr, action);

		// 主菜单默认按键挂机
		action = new ExitAction();
		IvrOperation.add(ivr, IvrOperation.mainMenu, "default", action);

		// 主菜单按0转前台分机
		action = new TransAction(C.TYPE_IN, "8000");
		IvrOperation.add(ivr, IvrOperation.mainMenu, "0", action);

		// 部门菜单 销售部请按01,业务部请按02,财务部请按03 ...
		action = new FieldAction("test/102", "2");
		node = IvrOperation.add(ivr, IvrOperation.mainMenu, "1", action);

		// 转销售部
		action = new TransAction(C.TYPE_IN, "8001");
		IvrOperation.add(ivr, node, "01", action);

		// 转业务部
		action = new TransAction(C.TYPE_IN, "8002");
		IvrOperation.add(ivr, node, "02", action);

		action = new ExitAction();
		IvrOperation.add(ivr, node, "default", action);

		// 转传真
		action = new TransAction(C.TYPE_RXFAX, "1");
		IvrOperation.add(ivr, IvrOperation.mainMenu, "9", action);

		// 公司简介
		action = new PlayAction("test/103");
		node = IvrOperation.add(ivr, IvrOperation.mainMenu, "3", action);

		action = new ExitAction();
		IvrOperation.add(ivr, node, "default", action);

		System.out.println(gson.toJson(ivr));

	}
}

class C {
	// 路由列表类型
	public static Type mapRoute = new TypeToken<Map<String, Route>>() {
	}.getType();
	// 分机列表类型
	public static Type mapSipPeer = new TypeToken<Map<String, SipPeer>>() {
	}.getType();
	// SIP中继列表类型
	public static Type mapSipTrunk = new TypeToken<Map<String, SipTrunk>>() {
	}.getType();

	// Ivr类型
	public static Type mapIvr = new TypeToken<Map<String, Map<String, String>>>() {
	}.getType();
	
	// 会议
	public static Type mapMeet = new TypeToken<Map<String, Meet>>() {
	}.getType();
	
	// 接收传真列表
	public static Type mapRxFax = new TypeToken<Map<String, RxFax>>() {
	}.getType();
	
	// 外拨路由规则
	public static Type mapOutRule = new TypeToken<Map<String, OutRule>>() {
	}.getType();

	// 路由类型
	public static final String TYPE_IVR = "to-ivr"; // IVR
	public static final String TYPE_QUEUE = "to-queue"; // 队列
	public static final String TYPE_MEET = "to-meet"; // MEET
	public static final String TYPE_RXFAX = "to-rxfax"; // 接收传真
	public static final String TYPE_IN = "to-in"; // 分机
	public static final String TYPE_OUT = "to-out"; // 外线

	// 外拨权限
	public static final String ACCESS_INTERNATIONAL = "I"; // 国际号码
	public static final String ACCESS_NATIONAL = "N"; // 国内号码
	public static final String ACCESS_LOCAL = "L"; // 市话号码

	// IVR动作类型
	public static final String ATYPE_SWITCH = "switch"; // 普通交换菜单,如:请直拨分机号查号请播0
	public static final String ATYPE_FIELD = "field"; // 菜单放音
	public static final String ATYPE_PLAY = "play"; // 放音
	public static final String ATYPE_RECORD = "record"; // 留言录音
	public static final String ATYPE_TRANS = "trans"; // 转移
	public static final String ATYPE_EXIT = "exit"; // 结束挂机
}

class SipPeer {
	String secret; // 分机密码
	String callerid; // 主叫号码
	String callgroup; // 分机分组
	String pickupgroup; // 允许代答组序列, 如: 1,2,5
	String callaccess; // 外拨权限
}

class SipTrunk {
	String host;
	String port;
	String limit;
}

class Route {
	String type; // 默认路由类型
	String target; // 默认路由目标, IVRID, 队列ID, 会议ID, 传真ID, 分机号码, 外线号码
	String zone; // 时段0, 如"21:00~8:00#123456"
	String zone_type; // 时段0路由类型
	String zone_target; // 时段0路由目标
	String zone1; // 时段1
	String zone1_type; // 时段1路由类型
	String zone1_target; // 时段1路由目标
}

class Meet{
	String password; //会议密码
}

class RxFax{
	String path;  //传真保存路径
}

class OutRule{	
	String prefix;  //前缀 允许为空
	String trunk; //中继
	String caller; //限定主叫呼出方向
	String transCaller; //转换后呼出主叫
}

class Network{
	String address; //地址
	String gateway; //网关
	String netmask; //掩码
}

class DF{
	String size; //磁盘大小(单位:M)
	String used; //已用
	String avail; //可用
	String use; //已用百分比
	String filesystem; //文件系统
	String mountedon; //挂载位置
}

class IvrOperation {
	public static final String mainMenu = "0";

	public static Map<String, String> genIvr() {
		Map<String, String> ivr = new HashMap<String, String>();
		return ivr;
	}

	public static String addMain(Map<String, String> ivr, IvrAction action) {
		ivr.put("0", action.toString());
		return "0";
	}

	public static String add(Map<String, String> ivr, String lastLevel, String selfLevel, IvrAction action) {
		String label = String.format("%s_%s", lastLevel, selfLevel);
		ivr.put(label, action.toString());
		return label;
	}
}

abstract class IvrAction {
	String atype; // 动作类型

	public IvrAction(String atype) {
		this.atype = atype;
	}

}

class SwitchAction extends IvrAction {
	String file; // 放音文件, 多个则以&连接

	String timeout = "10"; // 每次放音间隔单位秒
	String count = "3"; // 菜单放音次数

	String len; // 分机长度
	String prefix; // 分机前缀

	public SwitchAction(String file, String len, String prefix) {
		super(C.ATYPE_SWITCH);
		this.file = file;
		this.len = len;
		this.prefix = prefix;
	}

	public String toString() {
		return String.format("%s!%s!%s!%s!%s!%s", atype, file, timeout, count, len, prefix);
	}
}

class FieldAction extends IvrAction {
	String file; // 放音文件,多个则以&连接

	String len; // 0:无长度限制以#结束, >1为限制长度收码;
	String timeout = "10"; // 每次放音间隔单位秒
	String count = "3"; // 菜单放音次数

	public FieldAction(String file, String len) {
		super(C.ATYPE_FIELD);
		this.file = file;
		this.len = len;
	}

	public String toString() {
		return String.format("%s!%s!%s!%s!%s", atype, file, timeout, count, len);
	}
}

class TransAction extends IvrAction {
	String type; // 转移类型,同路由类型
	String target; // 转移目标

	public TransAction(String type, String target) {
		super(C.ATYPE_TRANS);
		this.type = type;
		this.target = target;
	}

	public String toString() {
		return String.format("%s!%s!%s", atype, type, target);
	}
}

class PlayAction extends IvrAction {
	String file; // 放音文件,多个则以&连接

	public PlayAction(String file) {
		super(C.ATYPE_PLAY);
		this.file = file;
	}

	public String toString() {
		return String.format("%s!%s", atype, file);
	}
}

class ExitAction extends IvrAction {

	public ExitAction() {
		super(C.ATYPE_EXIT);
	}

	public String toString() {
		return String.format("%s", atype);
	}
}
